

<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  
  <title>Cephx &mdash; Ceph Documentation</title>
  

  
  <link rel="stylesheet" href="../../_static/ceph.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/ceph.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/graphviz.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/custom.css" type="text/css" />

  
  

  
  

  

  
  <!--[if lt IE 9]>
    <script src="../../_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
    
      <script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
        <script src="../../_static/jquery.js"></script>
        <script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
        <script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
        <script src="../../_static/doctools.js"></script>
        <script src="../../_static/sphinx_highlight.js"></script>
    
    <script type="text/javascript" src="../../_static/js/theme.js"></script>

    
    <link rel="index" title="Index" href="../../genindex/" />
    <link rel="search" title="Search" href="../../search/" />
    <link rel="next" title="Cephx 认证协议详细阐述" href="../cephx_protocol/" />
    <link rel="prev" title="CephFS 快照" href="../cephfs-snapshots/" /> 
</head>

<body class="wy-body-for-nav">

   
  <header class="top-bar">
    <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="../../" class="icon icon-home" aria-label="Home"></a></li>
          <li class="breadcrumb-item"><a href="../internals/">Ceph 内幕</a></li>
      <li class="breadcrumb-item active">Cephx</li>
      <li class="wy-breadcrumbs-aside">
            <a href="../../_sources/dev/cephx.rst.txt" rel="nofollow"> View page source</a>
      </li>
  </ul>
  <hr/>
</div>
  </header>
  <div class="wy-grid-for-nav">
    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search"  style="background: #eee" >
          

          
            <a href="../../" class="icon icon-home"> Ceph
          

          
          </a>

          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search/" method="get">
    <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

          
        </div>

        
        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          
            
            
              
            
            
              <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../start/">Ceph 简介</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../install/">安装 Ceph</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../cephadm/">Cephadm</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../rados/">Ceph 存储集群</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../cephfs/">Ceph 文件系统</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../rbd/">Ceph 块设备</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../radosgw/">Ceph 对象网关</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../mgr/">Ceph 管理器守护进程</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../mgr/dashboard/">Ceph 仪表盘</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../monitoring/">监控概览</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../api/">API 文档</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../architecture/">体系结构</a></li>
<li class="toctree-l1"><a class="reference internal" href="../developer_guide/">开发者指南</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../internals/">Ceph 内幕</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../balancer-design/">Ceph 如何均衡（读写、容量）</a></li>
<li class="toctree-l2"><a class="reference internal" href="../blkin/">Tracing Ceph With LTTng</a></li>
<li class="toctree-l2"><a class="reference internal" href="../blkin/#tracing-ceph-with-blkin">Tracing Ceph With Blkin</a></li>
<li class="toctree-l2"><a class="reference internal" href="../bluestore/">BlueStore Internals</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ceph_krb_auth/">如何配置好 Ceph Kerberos 认证的详细文档</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cephfs-mirroring/">CephFS Mirroring</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cephfs-reclaim/">CephFS Reclaim Interface</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cephfs-snapshots/">CephFS 快照</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Cephx</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#intro">Intro</a></li>
<li class="toctree-l3"><a class="reference internal" href="#other-references">Other references</a></li>
<li class="toctree-l3"><a class="reference internal" href="#terms">Terms</a></li>
<li class="toctree-l3"><a class="reference internal" href="#terminology">Terminology</a></li>
<li class="toctree-l3"><a class="reference internal" href="#context">Context</a></li>
<li class="toctree-l3"><a class="reference internal" href="#phase-i-obtaining-auth-ticket">Phase I: obtaining auth ticket</a></li>
<li class="toctree-l3"><a class="reference internal" href="#phase-ii-obtaining-service-tickets-pre-nautilus">Phase II: Obtaining service tickets (pre-nautilus)</a></li>
<li class="toctree-l3"><a class="reference internal" href="#phase-iii-opening-a-connection-to-a-service">Phase III: Opening a connection to a service</a></li>
<li class="toctree-l3"><a class="reference internal" href="#rotating-service-secrets">Rotating service secrets</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../cephx_protocol/">Cephx 认证协议详细阐述</a></li>
<li class="toctree-l2"><a class="reference internal" href="../config/">配置管理系统</a></li>
<li class="toctree-l2"><a class="reference internal" href="../config-key/">config-key layout</a></li>
<li class="toctree-l2"><a class="reference internal" href="../context/">CephContext</a></li>
<li class="toctree-l2"><a class="reference internal" href="../continuous-integration/">Continuous Integration Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../corpus/">资料库结构</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cpu-profiler/">Oprofile 的安装</a></li>
<li class="toctree-l2"><a class="reference internal" href="../crush-msr/">CRUSH MSR (Multi-step Retry)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cxx/">C++17 and libstdc++ ABI</a></li>
<li class="toctree-l2"><a class="reference internal" href="../deduplication/">去重</a></li>
<li class="toctree-l2"><a class="reference internal" href="../delayed-delete/">CephFS delayed deletion</a></li>
<li class="toctree-l2"><a class="reference internal" href="../dev_cluster_deployment/">开发集群的部署</a></li>
<li class="toctree-l2"><a class="reference internal" href="../dev_cluster_deployment/#id5">在同一机器上部署多套开发集群</a></li>
<li class="toctree-l2"><a class="reference internal" href="../development-workflow/">开发流程</a></li>
<li class="toctree-l2"><a class="reference internal" href="../documenting/">为 Ceph 写作文档</a></li>
<li class="toctree-l2"><a class="reference internal" href="../dpdk/">Ceph messenger DPDKStack</a></li>
<li class="toctree-l2"><a class="reference internal" href="../encoding/">序列化（编码、解码）</a></li>
<li class="toctree-l2"><a class="reference internal" href="../erasure-coded-pool/">纠删码存储池</a></li>
<li class="toctree-l2"><a class="reference internal" href="../file-striping/">File striping</a></li>
<li class="toctree-l2"><a class="reference internal" href="../freebsd/">FreeBSD Implementation details</a></li>
<li class="toctree-l2"><a class="reference internal" href="../generatedocs/">Ceph 文档的构建</a></li>
<li class="toctree-l2"><a class="reference internal" href="../health-reports/">Health Reports</a></li>
<li class="toctree-l2"><a class="reference internal" href="../iana/">IANA 号</a></li>
<li class="toctree-l2"><a class="reference internal" href="../kclient/">Testing changes to the Linux Kernel CephFS driver</a></li>
<li class="toctree-l2"><a class="reference internal" href="../kclient/#step-one-build-the-kernel">Step One: build the kernel</a></li>
<li class="toctree-l2"><a class="reference internal" href="../kclient/#step-two-create-a-vm">Step Two: create a VM</a></li>
<li class="toctree-l2"><a class="reference internal" href="../kclient/#step-three-networking-the-vm">Step Three: Networking the VM</a></li>
<li class="toctree-l2"><a class="reference internal" href="../kubernetes/">Hacking on Ceph in Kubernetes with Rook</a></li>
<li class="toctree-l2"><a class="reference internal" href="../libcephfs_proxy/">Design of the libcephfs proxy</a></li>
<li class="toctree-l2"><a class="reference internal" href="../libs/">库体系结构</a></li>
<li class="toctree-l2"><a class="reference internal" href="../logging/">集群日志的用法</a></li>
<li class="toctree-l2"><a class="reference internal" href="../logs/">调试日志</a></li>
<li class="toctree-l2"><a class="reference internal" href="../macos/">在 MacOS 上构建</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mempool_accounting/">What is a mempool?</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mempool_accounting/#some-common-mempools-that-we-can-track">Some common mempools that we can track</a></li>
<li class="toctree-l2"><a class="reference internal" href="../messenger/">Messenger notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mon-bootstrap/">Monitor bootstrap</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mon-elections/">Monitor Elections</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mon-on-disk-formats/">ON-DISK FORMAT</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mon-osdmap-prune/">FULL OSDMAP VERSION PRUNING</a></li>
<li class="toctree-l2"><a class="reference internal" href="../msgr2/">msgr2 协议（ msgr2.0 和 msgr2.1 ）</a></li>
<li class="toctree-l2"><a class="reference internal" href="../network-encoding/">Network Encoding</a></li>
<li class="toctree-l2"><a class="reference internal" href="../network-protocol/">网络协议</a></li>
<li class="toctree-l2"><a class="reference internal" href="../object-store/">对象存储架构概述</a></li>
<li class="toctree-l2"><a class="reference internal" href="../osd-class-path/">OSD class path issues</a></li>
<li class="toctree-l2"><a class="reference internal" href="../peering/">互联</a></li>
<li class="toctree-l2"><a class="reference internal" href="../perf/">Using perf</a></li>
<li class="toctree-l2"><a class="reference internal" href="../perf_counters/">性能计数器</a></li>
<li class="toctree-l2"><a class="reference internal" href="../perf_histograms/">Perf histograms</a></li>
<li class="toctree-l2"><a class="reference internal" href="../placement-group/">PG （归置组）说明</a></li>
<li class="toctree-l2"><a class="reference internal" href="../quick_guide/">开发者指南（快速）</a></li>
<li class="toctree-l2"><a class="reference internal" href="../rados-client-protocol/">RADOS 客户端协议</a></li>
<li class="toctree-l2"><a class="reference internal" href="../rbd-diff/">RBD 增量备份</a></li>
<li class="toctree-l2"><a class="reference internal" href="../rbd-export/">RBD Export &amp; Import</a></li>
<li class="toctree-l2"><a class="reference internal" href="../rbd-layering/">RBD Layering</a></li>
<li class="toctree-l2"><a class="reference internal" href="../release-checklists/">Release checklists</a></li>
<li class="toctree-l2"><a class="reference internal" href="../release-process/">Ceph Release Process</a></li>
<li class="toctree-l2"><a class="reference internal" href="../seastore/">SeaStore</a></li>
<li class="toctree-l2"><a class="reference internal" href="../sepia/">Sepia 社区测试实验室</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session_authentication/">Session Authentication for the Cephx Protocol</a></li>
<li class="toctree-l2"><a class="reference internal" href="../testing/">测试笔记</a></li>
<li class="toctree-l2"><a class="reference internal" href="../versions/">Public OSD Version</a></li>
<li class="toctree-l2"><a class="reference internal" href="../vstart-ganesha/">NFS CephFS-RGW Developer Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="../wireshark/">Wireshark Dissector</a></li>
<li class="toctree-l2"><a class="reference internal" href="../zoned-storage/">Zoned Storage Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../osd_internals/">OSD 开发者文档</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mds_internals/">MDS 开发者文档</a></li>
<li class="toctree-l2"><a class="reference internal" href="../radosgw/">RADOS 网关开发者文档</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ceph-volume/">ceph-volume 开发者文档</a></li>
<li class="toctree-l2"><a class="reference internal" href="../crimson/">Crimson developer documentation</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../governance/">项目管理</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../foundation/">Ceph 基金会</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../ceph-volume/">ceph-volume</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../releases/general/">Ceph 版本（总目录）</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../releases/">Ceph 版本（索引）</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../security/">Security</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../hardware-monitoring/">硬件监控</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../glossary/">Ceph 术语</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../jaegertracing/">Tracing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../translation_cn/">中文版翻译资源</a></li>
</ul>

            
          
        </div>
        
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" aria-label="top navigation">
        
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="../../">Ceph</a>
        
      </nav>


      <div class="wy-nav-content">
        
        <div class="rst-content">
        
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
<div id="dev-warning" class="admonition note">
  <p class="first admonition-title">Notice</p>
  <p class="last">This document is for a development version of Ceph.</p>
</div>
  <div id="docubetter" align="right" style="padding: 5px; font-weight: bold;">
    <a href="https://pad.ceph.com/p/Report_Documentation_Bugs">Report a Documentation Bug</a>
  </div>

  
  <section id="cephx">
<h1>Cephx<a class="headerlink" href="#cephx" title="Permalink to this heading"></a></h1>
<section id="intro">
<span id="id1"></span><h2>Intro<a class="headerlink" href="#intro" title="Permalink to this heading"></a></h2>
<p>The protocol design looks a lot like kerberos.  The authorizer “KDC”
role is served by the monitor, who has a database of shared secrets
for each entity.  Clients and non-monitor daemons all start by
authenticating with the monitor to obtain tickets, mostly referred to
in the code as authorizers.  These tickets provide both
<em>authentication</em> and <em>authorization</em> in that they include a
description of the <em>capabilities</em> for the entity, a concise structured
description of what actions are allowed, that can be interpreted and
enforced by the service daemons.</p>
</section>
<section id="other-references">
<h2>Other references<a class="headerlink" href="#other-references" title="Permalink to this heading"></a></h2>
<ul class="simple">
<li><p>A write-up from 2012 on cephx as it existed at that time by Peter
Reiher: <a class="reference internal" href="../cephx_protocol/#cephx-2012-peter"><span class="std std-ref">Cephx 认证协议详细阐述</span></a></p></li>
</ul>
</section>
<section id="terms">
<h2>Terms<a class="headerlink" href="#terms" title="Permalink to this heading"></a></h2>
<ul class="simple">
<li><p><em>monitor(s)</em>: central authorization authority</p></li>
<li><p><em>service</em>: the set of all daemons of a particular type (e.g., all
OSDs, all MDSs)</p></li>
<li><p><em>client</em>: an entity or principal that is accessing the service</p></li>
<li><p><em>entity name</em>: the string identifier for a principal
(e.g. client.admin, osd.123)</p></li>
<li><p><em>ticket</em>: a bit of data that cryptographically asserts identify and
authorization</p></li>
<li><p><em>principal</em>: a client or daemon, identified by a unique entity_name,
that shares a secret with the monitor.</p></li>
<li><p><em>principal_secret</em>: principal secret, a shared secret (16 bytes)
known by the principal and the monitor</p></li>
<li><p><em>mon_secret</em>: monitor secret, a shared secret known by all monitors</p></li>
<li><p><em>service_secret</em>: a rotating secret known by all members of a
service class (e.g., all OSDs)</p></li>
<li><p><em>auth ticket</em>: a ticket proving identity to the monitors</p></li>
<li><p><em>service ticket</em>: a ticket proving identify and authorization to a
service</p></li>
</ul>
</section>
<section id="terminology">
<h2>Terminology<a class="headerlink" href="#terminology" title="Permalink to this heading"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">{foo,</span> <span class="pre">bar}^secret</span></code> denotes encryption by secret.</p>
</section>
<section id="context">
<h2>Context<a class="headerlink" href="#context" title="Permalink to this heading"></a></h2>
<p>The authentication messages described here are specific to the cephx
auth implementation.  The messages are transferred by the Messenger
protocol or by MAuth messages, depending on the version of the
messenger protocol.  See also <a class="reference internal" href="../msgr2/#msgr2-protocol"><span class="std std-ref">msgr2 协议（ msgr2.0 和 msgr2.1 ）</span></a>.</p>
<p>An initial (messenger) handshake negotiates an authentication method
to be used (cephx vs none or krb or whatever) and an assertion of what
entity the client or daemon is attempting to authenticate as.</p>
</section>
<section id="phase-i-obtaining-auth-ticket">
<h2>Phase I: obtaining auth ticket<a class="headerlink" href="#phase-i-obtaining-auth-ticket" title="Permalink to this heading"></a></h2>
<p>The cephx exchange begins with the monitor knowing who the client
claims to be, and an initial cephx message from the monitor to the
client/principal.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span><span class="o">-&gt;</span><span class="n">p</span> <span class="p">:</span>
  <span class="n">CephxServerChallenge</span> <span class="p">{</span>
    <span class="n">u64</span> <span class="n">server_challenge</span>     <span class="c1"># random (by server)</span>
  <span class="p">}</span>
</pre></div>
</div>
<p>The client responds by adding its own challenge, and calculating a
value derived from both challenges and its shared key
principal_secret.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">p</span><span class="o">-&gt;</span><span class="n">a</span> <span class="p">:</span>
  <span class="n">CephxRequestHeader</span> <span class="p">{</span>
    <span class="n">u16</span> <span class="n">CEPHX_GET_AUTH_SESSION_KEY</span>
  <span class="p">}</span>
  <span class="n">CephXAuthenticate</span> <span class="p">{</span>
    <span class="n">u8</span> <span class="mi">2</span>                     <span class="c1"># 2 means nautilus+</span>
    <span class="n">u64</span> <span class="n">client_challenge</span>     <span class="c1"># random (by client)</span>
    <span class="n">u64</span> <span class="n">key</span> <span class="o">=</span> <span class="p">{</span><span class="n">client_challenge</span> <span class="o">^</span> <span class="n">server_challenge</span><span class="p">}</span><span class="o">^</span><span class="n">principal_secret</span>   <span class="c1"># (roughly)</span>
    <span class="n">blob</span> <span class="n">old_ticket</span>          <span class="c1"># old ticket, if we are reconnecting or renewing</span>
    <span class="n">u32</span> <span class="n">other_keys</span>           <span class="c1"># bit mask of service keys we want</span>
  <span class="p">}</span>
</pre></div>
</div>
<p>Prior to nautilus,:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephXAuthenticate</span> <span class="p">{</span>
  <span class="n">u8</span> <span class="mi">1</span>                     <span class="c1"># 2 means nautilus+</span>
  <span class="n">u64</span> <span class="n">client_challenge</span>     <span class="c1"># random (by client)</span>
  <span class="n">u64</span> <span class="n">key</span> <span class="o">=</span> <span class="p">{</span><span class="n">client_challenge</span> <span class="o">+</span> <span class="n">server_challenge</span><span class="p">}</span><span class="o">^</span><span class="n">principal_secret</span>   <span class="c1"># (roughly)</span>
  <span class="n">blob</span> <span class="n">old_ticket</span>          <span class="c1"># old ticket, if we are reconnecting or renewing</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The monitor looks up principal_secret in database, and verifies the
key is correct.  If old_ticket is present, verify it is valid, and we
can reuse the same global_id.  (Otherwise, a new global_id is assigned
by the monitor.):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span><span class="o">-&gt;</span><span class="n">p</span> <span class="p">:</span>
  <span class="n">CephxReplyHeader</span> <span class="p">{</span>
    <span class="n">u16</span> <span class="n">CEPHX_GET_AUTH_SESSION_KEY</span>
    <span class="n">s32</span> <span class="n">result</span> <span class="p">(</span><span class="mi">0</span><span class="p">)</span>
  <span class="p">}</span>
  <span class="n">u8</span> <span class="n">encoding_version</span> <span class="o">=</span> <span class="mi">1</span>
  <span class="n">u32</span> <span class="n">num_tickets</span> <span class="p">(</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span>
  <span class="n">ticket_info</span>           <span class="c1"># (N = 1)</span>
</pre></div>
</div>
<p>plus (for Nautilus and later):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">u32</span> <span class="n">connection_secret_len</span>      <span class="c1"># in bytes</span>
<span class="n">connection_secret</span><span class="o">^</span><span class="n">session_key</span>
<span class="n">u32</span> <span class="n">other_keys_len</span>             <span class="c1"># bytes of other keys (encoded)</span>
<span class="n">other_keys</span> <span class="p">{</span>
  <span class="n">u8</span> <span class="n">encoding_version</span> <span class="o">=</span> <span class="mi">1</span>
  <span class="n">u32</span> <span class="n">num_tickets</span>
  <span class="n">service_ticket_info</span> <span class="o">*</span> <span class="n">N</span>      <span class="c1"># for each service ticket</span>
<span class="p">}</span>
</pre></div>
</div>
<p>where:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ticket_info</span> <span class="p">{</span>
  <span class="n">u32</span> <span class="n">service_id</span>       <span class="c1"># CEPH_ENTITY_TYPE_AUTH</span>
  <span class="n">u8</span> <span class="n">msg_version</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
  <span class="p">{</span><span class="n">CephXServiceTicket</span> <span class="n">service_ticket</span><span class="p">}</span><span class="o">^</span><span class="n">principal_secret</span>
  <span class="p">{</span><span class="n">CephxTicketBlob</span> <span class="n">ticket_blob</span><span class="p">}</span><span class="o">^</span><span class="n">existing</span> <span class="n">session_key</span>   <span class="c1"># if we are renewing a ticket,</span>
  <span class="n">CephxTicketBlob</span> <span class="n">ticket_blob</span>                          <span class="c1"># otherwise</span>
<span class="p">}</span>

<span class="n">service_ticket_info</span> <span class="p">{</span>
  <span class="n">u32</span> <span class="n">service_id</span>       <span class="c1"># CEPH_ENTITY_TYPE_{OSD,MDS,MGR}</span>
  <span class="n">u8</span> <span class="n">msg_version</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
  <span class="p">{</span><span class="n">CephXServiceTicket</span> <span class="n">service_ticket</span><span class="p">}</span><span class="o">^</span><span class="n">principal_secret</span>
  <span class="n">CephxTicketBlob</span> <span class="n">ticket_blob</span>
<span class="p">}</span>

<span class="n">CephxServiceTicket</span> <span class="p">{</span>
  <span class="n">CryptoKey</span> <span class="n">session_key</span>      <span class="c1"># freshly generated (even if old_ticket is present)</span>
  <span class="n">utime_t</span> <span class="n">expiration</span>         <span class="c1"># now + auth_mon_ticket_ttl</span>
<span class="p">}</span>

<span class="n">CephxTicketBlob</span> <span class="p">{</span>
  <span class="n">u64</span> <span class="n">secret_id</span>             <span class="c1"># which service ticket encrypted this; -1 == monsecret, otherwise service&#39;s rotating key id</span>
  <span class="p">{</span><span class="n">CephXServiceTicketInfo</span> <span class="n">ticket</span><span class="p">}</span><span class="o">^</span><span class="n">mon_secret</span>
<span class="p">}</span>

<span class="n">CephxServiceTicketInfo</span> <span class="p">{</span>
  <span class="n">CryptoKey</span> <span class="n">session_key</span>     <span class="c1"># same session_key as above</span>
  <span class="n">AuthTicket</span> <span class="n">ticket</span>
<span class="p">}</span>

<span class="n">AuthTicket</span> <span class="p">{</span>
  <span class="n">EntityName</span> <span class="n">name</span>           <span class="c1"># client&#39;s identity, as proven by its possession of principal_secret</span>
  <span class="n">u64</span> <span class="n">global_id</span>             <span class="c1"># newly assigned, or from old_ticket</span>
  <span class="n">utime_t</span> <span class="n">created</span><span class="p">,</span> <span class="n">renew_after</span><span class="p">,</span> <span class="n">expires</span>
  <span class="n">AuthCapsInfo</span>       <span class="c1"># what client is allowed to do</span>
  <span class="n">u32</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span>      <span class="c1"># unused</span>
<span class="p">}</span>
</pre></div>
</div>
<p>So: for each ticket, principal gets a part that it decrypts with its
secret to get the session_key (CephxServiceTicket).  And the
CephxTicketBlob is opaque (secured by the mon secret) but can be used
later to prove who we are and what we can do (see CephxAuthorizer
below).</p>
<p>For Nautilus+, we also include the service tickets.</p>
<p>The client can infer that the monitor is authentic because it can
decrypt the service_ticket with its secret (i.e., the server has its
secret key).</p>
</section>
<section id="phase-ii-obtaining-service-tickets-pre-nautilus">
<h2>Phase II: Obtaining service tickets (pre-nautilus)<a class="headerlink" href="#phase-ii-obtaining-service-tickets-pre-nautilus" title="Permalink to this heading"></a></h2>
<p>Now the client needs the keys used to talk to non-monitors (osd, mds,
mgr).:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">p</span><span class="o">-&gt;</span><span class="n">a</span> <span class="p">:</span>
  <span class="n">CephxRequestHeader</span> <span class="p">{</span>
    <span class="n">u16</span> <span class="n">CEPHX_GET_PRINCIPAL_SESSION_KEY</span>
  <span class="p">}</span>
  <span class="n">CephxAuthorizer</span> <span class="n">authorizer</span>
  <span class="n">CephxServiceTicketRequest</span> <span class="p">{</span>
    <span class="n">u32</span> <span class="n">keys</span>    <span class="c1"># bitmask of CEPH_ENTITY_TYPE_NAME (MGR, OSD, MDS, etc)</span>
  <span class="p">}</span>
</pre></div>
</div>
<p>where:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxAuthorizer</span> <span class="p">{</span>
  <span class="n">u8</span> <span class="n">AUTH_MODE_AUTHORIZER</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
  <span class="n">u64</span> <span class="n">global_id</span>
  <span class="n">u32</span> <span class="n">service_id</span>    <span class="c1"># CEPH_ENTITY_TYPE_*</span>
  <span class="n">CephxTicketBlob</span> <span class="n">auth_ticket</span>
  <span class="p">{</span><span class="n">CephxAuthorize</span> <span class="n">msg</span><span class="p">}</span><span class="o">^</span><span class="n">session_key</span>
<span class="p">}</span>

<span class="n">CephxAuthorize</span> <span class="n">msg</span> <span class="p">{</span>
  <span class="n">u8</span> <span class="mi">2</span>
  <span class="n">u64</span> <span class="n">nonce</span>                         <span class="c1"># random from client</span>
  <span class="nb">bool</span> <span class="n">have_challenge</span> <span class="o">=</span> <span class="n">false</span>       <span class="c1"># not used here</span>
  <span class="n">u64</span> <span class="n">server_challenge_plus_one</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># not used here</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The monitor validates the authorizer by decrypting the auth_ticket
with <code class="docutils literal notranslate"><span class="pre">mon_secret</span></code> and confirming that it says this principal is who
they say they are in the CephxAuthorizer fields.  Note that the nonce
random bytes aren’t used here (the field exists for Phase III below).</p>
<p>Assuming all is well, the authorizer can generate service tickets
based on the CEPH_ENTITY_TYPE_* bits in the <code class="docutils literal notranslate"><span class="pre">keys</span></code> bitmask.</p>
<p>The response looks like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxResponseHeader</span> <span class="p">{</span>
  <span class="n">u16</span> <span class="n">CEPHX_GET_PRINCIPAL_SESSION_KEY</span>
  <span class="n">s32</span> <span class="n">result</span> <span class="p">(</span><span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">}</span>
<span class="n">u8</span> <span class="n">encoding_version</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">u32</span> <span class="n">num_tickets</span>
<span class="n">ticket_info</span> <span class="o">*</span> <span class="n">N</span>
</pre></div>
</div>
<p>Where, as above,:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ticket_info</span> <span class="p">{</span>
  <span class="n">u32</span> <span class="n">service_id</span>      <span class="c1"># CEPH_ENTITY_TYPE_{OSD,MGR,MDS}</span>
  <span class="n">u8</span> <span class="n">msg_version</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
  <span class="p">{</span><span class="n">CephXServiceTicket</span> <span class="n">service_ticket</span><span class="p">}</span><span class="o">^</span><span class="n">principal_secret</span>
  <span class="n">CephxTicketBlob</span> <span class="n">ticket_blob</span>
<span class="p">}</span>

<span class="n">CephxServiceTicket</span> <span class="p">{</span>
  <span class="n">CryptoKey</span> <span class="n">session_key</span>
  <span class="n">utime_t</span> <span class="n">expiration</span>
<span class="p">}</span>

<span class="n">CephxTicketBlob</span> <span class="p">{</span>
  <span class="n">u64</span> <span class="n">secret_id</span>       <span class="c1"># which version of the (rotating) service ticket encrypted this</span>
  <span class="p">{</span><span class="n">CephXServiceTicketInfo</span> <span class="n">ticket</span><span class="p">}</span><span class="o">^</span><span class="n">rotating_service_secret</span>
<span class="p">}</span>

<span class="n">CephxServiceTicketInfo</span> <span class="p">{</span>
  <span class="n">CryptoKey</span> <span class="n">session_key</span>
  <span class="n">AuthTicket</span> <span class="n">ticket</span>
<span class="p">}</span>

<span class="n">AuthTicket</span> <span class="p">{</span>
  <span class="n">EntityName</span> <span class="n">name</span>
  <span class="n">u64</span> <span class="n">global_id</span>
  <span class="n">utime_t</span> <span class="n">created</span><span class="p">,</span> <span class="n">renew_after</span><span class="p">,</span> <span class="n">expires</span>
  <span class="n">AuthCapsInfo</span>       <span class="c1"># what you are allowed to do</span>
  <span class="n">u32</span> <span class="n">flags</span> <span class="o">=</span> <span class="mi">0</span>      <span class="c1"># unused</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This concludes the authentication exchange with the monitor.  The
client or daemon now has tickets to talk to the mon and all other
daemons of interest.</p>
</section>
<section id="phase-iii-opening-a-connection-to-a-service">
<h2>Phase III: Opening a connection to a service<a class="headerlink" href="#phase-iii-opening-a-connection-to-a-service" title="Permalink to this heading"></a></h2>
<p>When a connection is opened, an “authorizer” payload is sent:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">p</span><span class="o">-&gt;</span><span class="n">s</span> <span class="p">:</span>
  <span class="n">CephxAuthorizer</span> <span class="p">{</span>
    <span class="n">u8</span> <span class="n">AUTH_MODE_AUTHORIZER</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">u64</span> <span class="n">global_id</span>
    <span class="n">u32</span> <span class="n">service_id</span>    <span class="c1"># CEPH_ENTITY_TYPE_*</span>
    <span class="n">CephxTicketBlob</span> <span class="n">auth_ticket</span>
    <span class="p">{</span><span class="n">CephxAuthorize</span> <span class="n">msg</span><span class="p">}</span><span class="o">^</span><span class="n">session_key</span>
  <span class="p">}</span>

  <span class="n">CephxAuthorize</span> <span class="n">msg</span> <span class="p">{</span>
    <span class="n">u8</span> <span class="mi">2</span>
    <span class="n">u64</span> <span class="n">nonce</span>               <span class="c1"># random from client</span>
    <span class="nb">bool</span> <span class="n">have_challenge</span> <span class="o">=</span> <span class="n">false</span>
    <span class="n">u64</span> <span class="n">server_challenge_plus_one</span> <span class="o">=</span> <span class="mi">0</span>
  <span class="p">}</span>
</pre></div>
</div>
<p>Note that prior to the Luminous v12.2.6 or Mimic v13.2.2 releases, the
CephxAuthorize msg did not contain a challenge, and consisted only
of:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxAuthorize</span> <span class="n">msg</span> <span class="p">{</span>
  <span class="n">u8</span> <span class="mi">1</span>
  <span class="n">u64</span> <span class="n">nonce</span>               <span class="c1"># random from client</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The server will inspect the auth_ticket CephxTicketBlob (by decrypting
it with its current rotating service key).  If it is a pre-v12.2.6 or
pre-v13.2.2 client, the server immediately replies with:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span><span class="o">-&gt;</span><span class="n">p</span> <span class="p">:</span>
  <span class="p">{</span><span class="n">CephxAuthorizeReply</span> <span class="n">reply</span><span class="p">}</span><span class="o">^</span><span class="n">session_key</span>
</pre></div>
</div>
<p>where:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxAuthorizeReply</span> <span class="p">{</span>
  <span class="n">u64</span> <span class="n">nonce_plus_one</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Otherwise, the server will respond with a challenge (to prevent replay
attacks):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span><span class="o">-&gt;</span><span class="n">p</span> <span class="p">:</span>
  <span class="p">{</span><span class="n">CephxAuthorizeChallenge</span> <span class="n">challenge</span><span class="p">}</span><span class="o">^</span><span class="n">session_key</span>
</pre></div>
</div>
<p>where:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxAuthorizeChallenge</span> <span class="p">{</span>
  <span class="n">u64</span> <span class="n">server_challenge</span>        <span class="c1"># random from server</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The client decrypts and updates its CephxAuthorize msg accordingly,
resending most of the same information as before:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">p</span><span class="o">-&gt;</span><span class="n">s</span> <span class="p">:</span>
  <span class="n">CephxAuthorizer</span> <span class="p">{</span>
    <span class="n">u8</span> <span class="n">AUTH_MODE_AUTHORIZER</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">u64</span> <span class="n">global_id</span>
    <span class="n">u32</span> <span class="n">service_id</span>    <span class="c1"># CEPH_ENTITY_TYPE_*</span>
    <span class="n">CephxTicketBlob</span> <span class="n">auth_ticket</span>
    <span class="p">{</span><span class="n">CephxAuthorize</span> <span class="n">msg</span><span class="p">}</span><span class="o">^</span><span class="n">session_key</span>
  <span class="p">}</span>
</pre></div>
</div>
<p>where:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxAuthorize</span> <span class="n">msg</span> <span class="p">{</span>
  <span class="n">u8</span> <span class="mi">2</span>
  <span class="n">u64</span> <span class="n">nonce</span>                        <span class="c1"># (new) random from client</span>
  <span class="nb">bool</span> <span class="n">have_challenge</span> <span class="o">=</span> <span class="n">true</span>
  <span class="n">u64</span> <span class="n">server_challenge_plus_one</span>    <span class="c1"># server_challenge + 1</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The server validates the ticket as before, and then also verifies the
msg nonce has it’s challenge + 1, confirming this is a live
authentication attempt (not a replay).</p>
<p>Finally, the server responds with a reply that proves its authenticity
to the client.  It also includes some entropy to use for encryption of
the session, if it is needed for the mode.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span><span class="o">-&gt;</span><span class="n">p</span> <span class="p">:</span>
  <span class="p">{</span><span class="n">CephxAuthorizeReply</span> <span class="n">reply</span><span class="p">}</span><span class="o">^</span><span class="n">session_key</span>
</pre></div>
</div>
<p>where:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxAuthorizeReply</span> <span class="p">{</span>
  <span class="n">u64</span> <span class="n">nonce_plus_one</span>
  <span class="n">u32</span> <span class="n">connection_secret_length</span>
  <span class="n">connection</span> <span class="n">secret</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Prior to nautilus, there is no connection secret:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">CephxAuthorizeReply</span> <span class="p">{</span>
  <span class="n">u64</span> <span class="n">nonce_plus_one</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The client decrypts and confirms that the server incremented nonce
properly and that this is thus a live authentication request and not a
replay.</p>
</section>
<section id="rotating-service-secrets">
<h2>Rotating service secrets<a class="headerlink" href="#rotating-service-secrets" title="Permalink to this heading"></a></h2>
<p>Daemons make use of a rotating secret for their tickets instead of a
fixed secret in order to limit the severity of a compromised daemon.
If a daemon’s secret key is compromised by an attacker, that daemon
and its key can be removed from the monitor’s database, but the
attacker may also have obtained a copy of the service secret shared by
all daemons.  To mitigate this, service keys rotate periodically so
that after a period of time (auth_service_ticket_ttl) the key the
attacker obtained will no longer be valid.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">p</span><span class="o">-&gt;</span><span class="n">a</span> <span class="p">:</span>
  <span class="n">CephxRequestHeader</span> <span class="p">{</span>
    <span class="n">u16</span> <span class="n">CEPHX_GET_ROTATING_KEY</span>
  <span class="p">}</span>

<span class="n">a</span><span class="o">-&gt;</span><span class="n">p</span> <span class="p">:</span>
  <span class="n">CephxReplyHeader</span> <span class="p">{</span>
    <span class="n">u16</span> <span class="n">CEPHX_GET_ROTATING_KEY</span>
    <span class="n">s32</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span>
  <span class="p">}</span>
  <span class="p">{</span><span class="n">CryptoKey</span> <span class="n">service_key</span><span class="p">}</span><span class="o">^</span><span class="n">principal_secret</span>
</pre></div>
</div>
<p>That is, the new rotating key is simply protected by the daemon’s
rotating secret.</p>
<p>Note that, as an implementation detail, the services keep the current
key and the prior key on hand so that they can continue to validate
requests while the key is being rotated.</p>
</section>
</section>



<div id="support-the-ceph-foundation" class="admonition note">
  <p class="first admonition-title">Brought to you by the Ceph Foundation</p>
  <p class="last">The Ceph Documentation is a community resource funded and hosted by the non-profit <a href="https://ceph.io/en/foundation/">Ceph Foundation</a>. If you would like to support this and our other efforts, please consider <a href="https://ceph.io/en/foundation/join/">joining now</a>.</p>
</div>


           </div>
           
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="../cephfs-snapshots/" class="btn btn-neutral float-left" title="CephFS 快照" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
        <a href="../cephx_protocol/" class="btn btn-neutral float-right" title="Cephx 认证协议详细阐述" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; Copyright 2016, Ceph authors and contributors. Licensed under Creative Commons Attribution Share Alike 3.0 (CC-BY-SA-3.0).</p>
  </div>

   

</footer>
        </div>
      </div>

    </section>

  </div>
  

  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>

  
  
    
   

</body>
</html>